<?php
	/**
	  * @package	MyTools
	  * @name		CalendarCreator
	  * @brief		Clase para crear un calendario de acuerdo a los parametros recibidos
	  * @author		Hermann D. Schimpf <hschimpf@gschimpf.com>
	  * @license	http://opensource.org/licenses/gpl-2.0.php
	  * @date		2010-01-04
	  * @version	0.1.0
  	**/

	final class CalendarCreator extends MyDebuger implements MyVersions {
		/* version de la clase */
		private static $version			= 0;
		/* subversion de la clase */
		private static $subversion		= 1;
		/* numero de revision de la clase */
		private static $revision		= 0;

		/* ano del que crearemos el calendario */
		private $year		= False;
		/* mes del que crearemos el calendario */
		private $month		= False;
		/* fecha temporal de proceso */
		private $date		= False;
		/* dia primero de la semama del calendario */
		private $first		= False;
		/* dias totales del mes */
		private $totDays	= False;
		/* calendario resultante */
		private $calendar	= False;
		/* almacenamos la lista de dias */
		private $days		= Array(1 => 'Dom', 'Lun', 'Mar', 'Mie', 'Jue', 'Vie', 'Sab');
		/* almacenamos la lista de meses */
		private $months	= Array(1 => 'Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre');

		public function __construct($debug = False) {
			/* creamos el padre */
			parent::__construct($debug, __CLASS__);
		}

		public function __destruct() {
			/* matamos el padre */
			parent::__destruct();
		}

		public static final function getVersion() {
			/* retornamos la version actual de la clase */
			return 'v' . self::$version . '.' . self::$subversion . '.' . self::$revision;
		}

		public static function getCalendar($year = Null, $month = Null, $debug = False) {
			/* ingresamos a un control de errores para capturar mis excepciones */
			try {
				/* ingresamos a un control de errores para capturar las excepciones de ejecucion */
				try {
					/* creamos una instancia */
					$getCalendar = new CalendarCreator($debug);
					/* verificamos y almacenamos los datos recibidos */
					$getCalendar->saveData($year, $month);
					/* retornamos el calendario */
					return $getCalendar->buildCalendar();
				/* capturamos las excepciones */
				} catch (Exception $e) {
					/* capturamos todos los errores y los transformamos en mi excepcion */
					$getCalendar->newException($e);
				}
			/* capturamos mis excepciones */
			} catch (MyException $e) {
				/* si se produjo una excepcion la manejamos con el metodo 'show' */
				$getCalendar->show($e->getMensaje());
			}
		}

		private function saveData($year, $month) {
			/* mostramos un mensaje */
			$this->show('Verificando datos recibidos..', False);
			/* almacenamos el ano */
			$this->year = (
				/* verificamos si especifico el ano */
				$year === Null ?
				/* almacenamos el ano actual */
				date('Y') :
				/* almacenamos el ano especificado */
				$year
			);
			/* almacenamos el ano */
			$this->month = (
				/* verificamos si especifico el mes */
				$month === Null ?
				/* almacenamos el mes actual */
				date('m') :
				/* almacenamos el mes especificado */
				$month
			);
			/* mostramos ok al mensaje */
			$this->showOK();
		}

		private function buildCalendar() {
			/* realizamos verificaciones con el ano */
			$this->verificarAno();
			/* obtenemos datos del mes a crear */
			$this->obtenerDatosFecha();
			/* armamos el calendario */
			$this->armarCalendario();
			/* retornamos el calendario */
			return $this->resultCalendar();
		}

		private function verificarAno() {
			/* mostramos un mensaje */
			$this->show('Normalizando ano..', False);
			/* verificamos si el ano ingresado es mayor a 0 y menor a 30 */
			if ($this->year >= 0 && $this->year < 30)
				/* agregamos al ano 2000 anos */
				$this->year += 2000;
			/* verificamos si el ano ingresado es mayor a 30 y menor a 100 */
			if ($this->year >= 30 && $this->year < 100)
				/* agregamos al ano 1900 anos */
				$this->year += 1900;
			/* mostramos ok al mensaje */
			$this->showOK();
		}

		private function obtenerDatosFecha() {
			/* creamos una fecha con el dia primero del mes */
			$this->date = mktime(0, 0, 0, $this->month, 1, $this->year);
			/* obtenemos el dia inicial de la semana */
			$this->first = date('w', $this->date);
			/* obtenemos la cantidad de dias totales del mes */
			$this->totDays = date('t', $this->date);
		}

		private function armarCalendario() {
			/* mostramos un mensaje */
			$this->show('Armando calendario para el mes ' . $this->bold($this->year . '-' . $this->month) . '..');
			/* armamos el encabezado del calendario */
			$this->buildHead();
			/* agregamos las celdas vacias */
			$this->addEmptyCelds();
			/* agregamos los dias del mes */
			$this->addMonthDays();
			/* finalizamos el calendario */
			$this->endCalendar();
		}

		private function buildHead() {
			/* mostramos un mensaje */
			$this->show('Agregando cabecera al calendario..', False);
			/* iniciamos una tabla */
			$this->calendar = '<TABLE id=\'calendar' . $this->year . $this->month . '\'>';
			/* iniciamos la cabecera para los dias */
			$this->calendar .= '<TR>';
			/* recorremos los dias */
			foreach ($this->days AS $dayNum => $day)
				/* agregamos el dia */
				$this->calendar .= '<TD class=\'calendarHead\' id=\'head' . ($dayNum < 10 ? '0' . $dayNum : $dayNum) . '\'>' . $day . '</TD>';
			/* finalizamos la cabecera para los dias */
			$this->calendar .= '</TR>';
			/* mostramos ok al mensaje */
			$this->showOK();
		}

		private function addEmptyCelds() {
			/* mostramos un mensaje */
			$this->show('Agregando espacios vacios del calendario..', False);
			/* iniciamos una fila */
			$this->calendar .= '<TR>';
			/* ingresamos a un ciclo agregando los dias vacios */
			for ($i = 0; $i < $this->first; $i++)
				/* agregamos la celda vacia */
				$this->calendar .= '<TD class=\'calendarDay\'></TD>';
			/* mostramos ok al mensaje */
			$this->showOK();
		}

		private function addMonthDays() {
			/* mostramos un mensaje */
			$this->show('Agregando dias del calendario..', False);
			/* ingresamos a un ciclo para agregar los dias del mes restantes */
			for ($day = 1; $day <= $this->totDays; $day++) {
				/* creamos una fecha con el dia actual */
				$this->date = mktime(0, 0, 0, $this->month, $day, $this->year);
				/* obtenemos el primer dia de la semana */
				$this->first = date('w', $this->date);
				/* agregamos el dia */
				$this->calendar .= '<TD class=\'calendarDay\' id=\'day' . $this->year . $this->month . ($day < 10 ? '0' . $day : $day) . '\'>' . $day . '</TD>';
				/* verificamos si el dia de la semana es sabado */
				if ($this->first == 6)
					/* finalizamos la semana e iniciamos otra */
					$this->calendar .= '</TR><TR>';
			}
			/* mostramos ok al mensaje */
			$this->showOK();
		}

		private function endCalendar() {
			/* mostramos un mensaje */
			$this->show('Finalizando el calendario..', False);
			/* finalizamos la semana */
			$this->calendar .= '</TR>';
			/* finalizamos el calendario */
			$this->calendar .= '</TABLE>';
			/* mostramos ok al mensaje */
			$this->showOK();
		}

		private function resultCalendar() {
			/* retornamos el calendario finalizado */
			return $this->calendar;
		}
	}
?>